package com.aaa.websocketdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okio.ByteString;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 测试别人提供的服务端
//        WebSocketTest("");

        // 自己即是服务端也是客户端
        MockWebSocket();

        // 测试javaLib中的服务端
//        WebSocketTest("ws:127.0.0.1:52721");
    }

    /**
     * 建立WebSocket连接
     */
    public void WebSocketTest(String url) {
//        OkHttpClient client = new OkHttpClient();

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        OkHttpClient client = clientBuilder.pingInterval(59, TimeUnit.SECONDS)
                .build();

        // http://www.websocket-test.com/
        String webSocketUrl = "ws://121.40.165.18:8800";
        // http://coolaf.com/tool/chattest
//        webSocketUrl = "ws://123.207.136.134:9010/ajaxchattest"; // onFailure

        if (!TextUtils.isEmpty(url)) {
            webSocketUrl = url;
        }

        Request.Builder requestBuilder = new Request.Builder();
        Request request = requestBuilder.url(webSocketUrl)
                .header("myToken", Thread.currentThread().getName() + "/" + (System.currentTimeMillis() & 0b11111111))
                .build();

        Log.i(TAG, "WebSocketTest: " + Thread.currentThread());
        client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosed(webSocket, code, reason);
                Log.i(TAG, "onClosed: " + Thread.currentThread());
            }

            @Override
            public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosing(webSocket, code, reason);
                Log.i(TAG, "onClosing: " + Thread.currentThread());
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                Log.i(TAG, "onFailure: " + Thread.currentThread());
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                super.onMessage(webSocket, text);
                Log.i(TAG, "onMessage: text " + text + " " + Thread.currentThread());
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {
                super.onMessage(webSocket, bytes);
                Log.i(TAG, "onMessage: bytes " + Thread.currentThread());
            }

            @Override
            public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
                super.onOpen(webSocket, response);
                Log.i(TAG, "onOpen: " + Thread.currentThread());
            }
        });
    }

    /**
     * 模拟WebSocket服务器
     */
    public void MockWebSocket() {
        final String TAG_mock = "MockWebSocket";

        final MockWebServer mockWebServer = new MockWebServer();
        mockWebServer.enqueue(new MockResponse().withWebSocketUpgrade(new WebSocketListener() {
            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosed(webSocket, code, reason);
                Log.i(TAG_mock, "onClosed: ");
            }

            @Override
            public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosing(webSocket, code, reason);
                Log.i(TAG_mock, "onClosing: ");
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                Log.i(TAG_mock, "onFailure: ");
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                super.onMessage(webSocket, text);
                Log.i(TAG_mock, "onMessage: ");
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {
                super.onMessage(webSocket, bytes);
                Log.i(TAG_mock, "onMessage: ");
            }

            @Override
            public void onOpen(@NotNull final WebSocket webSocket, @NotNull Response response) {
                super.onOpen(webSocket, response);
                Log.i(TAG_mock, "onOpen: response=" + response);
                Log.i(TAG_mock, "onOpen: request=" + webSocket.request());

                webSocket.send("您好，这里是服务器，有什么可以为你效劳？");

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(30 * 1000);
                            webSocket.send("30秒后，查看链接是否还在");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }));

        /**
         * 服务器建立后，获取IP地址和端口必须在子线程，否则 NetworkOnMainThreadException
         *
         * 让客户端用获取到的url连接服务器
         * */
        new Thread(new Runnable() {
            @Override
            public void run() {
                String hostName = mockWebServer.getHostName();
                int port = mockWebServer.getPort();
//                Log.i(TAG_mock, "MockWebSocket: hostName=" + hostName + " port=" + port);
                final String url = "ws:" + hostName + ":" + port;
                Log.i(TAG_mock, "MockWebSocket: url=" + url);
                for (int i = 0; i < 10; i++) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Log.i(TAG_mock, "MockWebSocket: WebSocketTest " + Thread.currentThread());
                            WebSocketTest(url);
                        }
                    }).start();
                }
            }
        }).start();

    }
}
